package com.neusoft.neuiotms.dcam.workflow.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;

import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.activiti.dto.ProcessInstanceDTO;
import com.neusoft.bizcore.activiti.service.ProcessInstanceService;
import com.neusoft.bizcore.activiti.service.WorkOrderService;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.neuiotms.common.constant.AHConstants;
import com.neusoft.neuiotms.dcam.anhui.itsm.WorkflowBean;
import com.neusoft.neuiotms.dcam.constant.DCAMConsts;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetLifeCycleDTO;
import com.neusoft.neuiotms.dcam.fixed.model.Asset;
import com.neusoft.neuiotms.dcam.fixed.repository.AssetRepository;
import com.neusoft.neuiotms.dcam.fixed.service.AssetLifeCycleService;
import com.neusoft.neuiotms.dcam.fixed.service.AssetService;
import com.neusoft.neuiotms.dcam.fixed.service.ItsmService;
import com.neusoft.neuiotms.dcam.workflow.converter.DiaoboKJConverter;
import com.neusoft.neuiotms.dcam.workflow.converter.ITSMApproveConverter;
import com.neusoft.neuiotms.dcam.workflow.dto.DiaoboItemKJDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.DiaoboKJDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.ITSMApproveDTO;
import com.neusoft.neuiotms.dcam.workflow.model.DiaoboItemKJ;
import com.neusoft.neuiotms.dcam.workflow.model.DiaoboKJ;
import com.neusoft.neuiotms.dcam.workflow.model.ITSMApprove;
import com.neusoft.neuiotms.dcam.workflow.repository.DiaoboItemKJRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.DiaoboKJRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.ITSMApproveRepository;
import com.neusoft.neuiotms.dcam.workflow.service.DiaoboKJService;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;

import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class DiaoboKJServiceImpl implements DiaoboKJService {

    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private ProcessInstanceService processInstanceService;
    @Autowired
    private DiaoboKJRepository diaoboKJRepository;
    @Autowired
    private DiaoboKJConverter diaoboKJConverter;
    @Autowired
    private ITSMApproveRepository approveRepository;
    @Autowired
    private ITSMApproveConverter approveConverter;
    @Autowired
    private DiaoboItemKJRepository diaoboItemKJRepository;
    @Autowired
    private AssetRepository assetRepository;
    @Autowired
    private AssetService assetService;
    @Autowired
    private AuthMicroService authMicroService;
    @Autowired
    private AssetLifeCycleService assetLifeCycleService;
    @Autowired
    private ItsmService itsmService;

    @Override
    @Transactional
    public DiaoboKJDTO create(final DiaoboKJDTO dto, final UserBean user) {

        final String taskId = dto.getTaskId();
        final ProcessInstanceDTO instance =
                this.workOrderService.submit(dto.getTitle(), DCAMConsts.PROCESSS_DIAOBO_KJ_KEY, dto.getWorkOrderNum(),
                        user);
        dto.setTaskId(instance.getTaskId());
        dto.setWorkOrderNum(instance.getWorkorderNum());
        dto.setCreateUser(user.getUsername());
        dto.setCreateUserName(user.getName());

        // 查询当前workOrderNum和TaskId下是否存在记录
        final DiaoboKJ oldModel = this.diaoboKJRepository.findByWorkOrderNumAndTaskId(
                dto.getWorkOrderNum(), taskId);
        if (oldModel == null) {
            dto.setId(null);
        }

        // 解锁以前的资产信息
        final List<DiaoboItemKJ> all = this.diaoboItemKJRepository.findByMain_WorkOrderNum(dto.getWorkOrderNum());
        if (null != all) {
            this.assetService.updateLocked(all.stream().map(l -> l.getCode()).distinct().collect(Collectors.toList()),
                    false);
        }

        DiaoboKJ model = this.diaoboKJConverter.toModel(dto);
        model = this.diaoboKJRepository.save(model);

        // 枷锁资产信息
        this.assetService.updateLocked(
                model.getDetails().stream().map(l -> l.getCode()).distinct().collect(Collectors.toList()),
                true);

        List<String> users = new ArrayList<>();
        final Map<String, Object> search = new HashMap<>();
        search.put("s_orgCode", dto.getDestManagementOrgCode());
        search.put("s_roleCode", AHConstants.ROLE_KJ_DEPT_ASSET_ADMIN);
        final ResultListDTO<Map<String, Object>> userList = this.authMicroService.userIndex(search);
        users = userList.getData().stream().map(l -> l.get("username").toString()).filter(s -> null != s)
                .collect(Collectors.toList());

        if (users.isEmpty()) {
            throw new UnitedException(dto.getDestManagementOrgName() + "部门资产管理员不存在,联系系统管理员");
        }

        this.processInstanceService.setGlobalVariable(dto.getTaskId(), DCAMConsts.PROCESSS_DISPATCHUSERLIST,
                users);

        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);

        try {
            // 对接ITSM
            final List<WorkflowBean.AssetBean> assetList = Lists.newArrayList();
            for (final DiaoboItemKJDTO item : dto.getDetails()) {
                final WorkflowBean.AssetBean assetBean = WorkflowBean.AssetBean.builder()
                        .assetId(item.getCode())
                        .assetClassID(item.getSmallTypeCode())
                        .assetModel(item.getSpecifications())
                        .assetUnit("未知")
                        .assetPrice(0)
                        .assetNumber(1)
                        .assetName(item.getName())
                        .assetType("1")
                        .assetSign("未知")
                        .build();
                assetList.add(assetBean);
            }

            final WorkflowBean workflowBean = WorkflowBean.builder()
                    .workNum(dto.getWorkOrderNum())
                    .workName("设备调拨")
                    .workType("50")
                    .workContent("设备调拨申请")
                    .applyUser(user.getUsername())
                    .departmentTo(dto.getDestManagementOrgName())
                    .assetList(assetList)
                    .build();

            this.itsmService.pushItsm(workflowBean);
        } catch (final Exception e) {
            DiaoboKJServiceImpl.log.error("设备调拨流程推送ITSM时发生错误", e);
        }

        return this.diaoboKJConverter.toDTO(model);
    }

    @Override
    public DiaoboKJDTO detail(final String workOrderNum, final String taskId, final UserBean user) {
        DiaoboKJ model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.diaoboKJRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        return new DiaoboKJDTO();
                    } else {
                        model = this.diaoboKJRepository.findByWorkOrderNumAndTaskId(workOrderNum,
                                lastTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                final List<DiaoboKJ> DiaoboKJs =
                        this.diaoboKJRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
                if ((DiaoboKJs != null) && (DiaoboKJs.size() > 0)) {
                    model = DiaoboKJs.get(0);
                }
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.diaoboKJConverter.toDTO(model);
    }

    @Override
    @Transactional
    public ITSMApproveDTO itsmCreate(final ITSMApproveDTO dto, final UserBean user) {
        final ITSMApprove model = this.approveConverter.toModel(dto);
        this.approveRepository.save(model);

        this.processInstanceService.setGlobalVariable(dto.getTaskId(), DCAMConsts.PROCESSS_DIAOBO_KJ_APPROVE_RESULT,
                dto.getResult());
        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);

        // 更新资产状态为转移中
        if ("1".equals(dto.getResult())) {
            final DiaoboKJ diaobo =
                    this.diaoboKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(dto.getWorkOrderNum());

            final List<String> codes = diaobo.getDetails().stream().map(l -> l.getCode()).distinct()
                    .collect(Collectors.toList());
            this.assetService.updateStatus(codes, DCAMConsts.ASSET_STATUS_TRANSFER);
        }

        return this.approveConverter.toDTO(model);
    }

    @Override
    public ITSMApproveDTO itsmDetails(final String workOrderNum, final String taskId, final UserBean user) {
        ITSMApprove model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.approveRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        return new ITSMApproveDTO();
                    } else {
                        model = this.approveRepository.findByWorkOrderNumAndTaskId(workOrderNum,
                                lastTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                final List<ITSMApprove> DiaoboKJs =
                        this.approveRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
                if ((DiaoboKJs != null) && (DiaoboKJs.size() > 0)) {
                    model = DiaoboKJs.get(0);
                }
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.approveConverter.toDTO(model);
    }

    @Transactional
    @Override
    public void confirmCreate(final DiaoboKJDTO dto, final UserBean user) {

        final List<DiaoboItemKJ> models = dto.getDetails().stream().map(l -> {
            final DiaoboItemKJ model = this.diaoboItemKJRepository.getOne(l.getId());
            model.setDiaoboLocation(l.getDiaoboLocation());
            model.setDiaoboLocationName(l.getDiaoboLocationName());
            model.setDiaoboUserCode(l.getDiaoboUserCode());
            model.setDiaoboUserName(l.getDiaoboUserName());
            return model;
        }).collect(Collectors.toList());

        this.diaoboItemKJRepository.saveAll(models);

        this.diaoboKJCompleteUpdate(dto);

        this.processInstanceService.setGlobalVariable(dto.getTaskId(),
                "passFlag", true);
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);
    }

    @Override
    public DiaoboKJDTO confirmDetails(final String workOrderNum, final String taskId, final UserBean user) {
        final DiaoboKJ model =
                this.diaoboKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
        if (model != null) {
            return this.diaoboKJConverter.toDTO(model);
        }
        return new DiaoboKJDTO();
    }

    private void diaoboKJCompleteUpdate(final DiaoboKJDTO model) {

        final List<AssetLifeCycleDTO> lifeList = new ArrayList<>();
        final List<Asset> assets = new ArrayList<>();

        if (model != null) {

            model.getDetails().stream().map(l -> {
                final Asset asset = this.assetRepository.findByCode(l.getCode());
                asset.setLocked(false);
                asset.setLocation(l.getDiaoboLocation());
                asset.setLocationName(l.getDiaoboLocationName());
                asset.setManagementOrgCode(model.getDestManagementOrgCode());
                asset.setManagementOrgName(model.getDestManagementOrgName());
                asset.setManagementUserCode(l.getDiaoboUserCode());
                asset.setManagementUserName(l.getDiaoboUserName());
                if (StringUtils.isEmpty(l.getDiaoboUserCode())) {
                    asset.setStatus(DCAMConsts.ASSET_STATUS_UNUSED);
                } else {
                    asset.setStatus(DCAMConsts.ASSET_STATUS_USED);
                }
                // 生命周期
                lifeList.add(AssetLifeCycleDTO.builder().code(l.getCode())
                        .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_DIAOBO)
                        .content(l.getName() + "已经被调拨到" + model.getDestManagementOrgName() + "部门")
                        .workNum(model.getWorkOrderNum()).build());
                return asset;
            }).forEach(assets::add);

            if (assets.size() > 0) {
                this.assetRepository.saveAll(assets);
            }

            if (lifeList.size() > 0) {
                this.assetLifeCycleService.batchCreate(lifeList);
            }
        }
    }

}
